package gframework.bean.table;

import java.awt.Point;
import java.util.Vector;
import java.util.Comparator;
import java.util.Collections;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.event.TableModelEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JTable;

public class GTableModel extends DefaultTableModel implements Comparator {

    protected int currCol;
    protected Vector ascendCol;
    protected Integer one = new Integer(1);
    protected Integer minusOne = new Integer(-1);
    private Vector<Integer> colunasEditaveis;
    private Vector<Object> parser;

    public void setParser(Vector<Object> parser) {
        this.parser = parser;
    }

    public void setColunasEditaveis(Vector<Integer> colunasEditaveis) {
        this.colunasEditaveis = colunasEditaveis;
    }

    public GTableModel() {
        super();
        ascendCol = new Vector();
    }

    public GTableModel(Object[][] data, Object[] titles) {
        super(data, titles);
        ascendCol = new Vector();
    }

    public GTableModel(Vector data, Vector titles) {
        String[][] arrayDados = new String[data.size()][titles.size()];
        
        for (int i = 0; i < data.size(); i++) {
            String[] arrayLinha = new String[titles.size()];
            ((Vector) data.elementAt(i)).toArray(arrayLinha);
            arrayDados[i] = arrayLinha;
        }

        String[] arrayTitulos = new String[titles.size()];
        titles.toArray(arrayTitulos);

        this.setDataVector(arrayDados, arrayTitulos);
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return (colunasEditaveis.contains(col));
    }
    
    @Override
    public Class getColumnClass(int c) {
        try {
            if (getValueAt(0, c) == null) {
                return Object.class;
            }

            return getValueAt(0, c).getClass();
            
        } catch (Exception ex) {
            return Object.class;
        }
    }

    @Override
    public void addColumn(Object columnName) {
        super.addColumn(columnName);
        ascendCol.add(one);
    }

    @Override
    public void addColumn(Object columnName, Object[] columnData) {
        super.addColumn(columnName, columnData);
        ascendCol.add(one);
    }

    @Override
    public void addColumn(Object columnName, Vector columnData) {
        super.addColumn(columnName, columnData);
        ascendCol.add(one);
    }

    public int compare(Object v1, Object v2) {
        int ascending = ((Integer) ascendCol.get(currCol)).intValue();
        
        if (v1 == null && v2 == null) {
            return 0;
        } else if (v2 == null) {
            return 1 * ascending;
        } else if (v1 == null) {
            return -1 * ascending;
        }

        Object o1 = ((Vector) v1).get(currCol);
        Object o2 = ((Vector) v2).get(currCol);

        if (o1 == null && o2 == null) {
            return 0;
        } else if (o2 == null) {
            return 1 * ascending;
        } else if (o1 == null) {
            return -1 * ascending;
        }

        Object oParser = parser.get(currCol);

        if (o1 instanceof Number && o2 instanceof Number) {
            Number n1 = (Number) o1;
            Number n2 = (Number) o2;

            return Double.compare(n1.doubleValue(), n2.doubleValue()) * ascending;

        } else if (oParser instanceof SimpleDateFormat) {
            try {
                Date d1 = ((SimpleDateFormat) oParser).parse(o1.toString());
                Date d2 = ((SimpleDateFormat) oParser).parse(o2.toString());
                return d1.compareTo(d2) * ascending;
            
            } catch (ParseException parseException) {
            
            }
        } else if (oParser instanceof DecimalFormat) {
            try {
                Number n1 = ((DecimalFormat) oParser).parse(o1.toString());
                Number n2 = ((DecimalFormat) oParser).parse(o2.toString());
                
                return Double.compare(n1.doubleValue(), n2.doubleValue()) * ascending;
                
            } catch (ParseException parseException) {
            
            }
        } else if (o1 instanceof Comparable && o2 instanceof Comparable) {
            Comparable c1 = (Comparable) o1;
            Comparable c2 = (Comparable) o2;

            try {
                return c1.compareTo(c2) * ascending;
            
            } catch (ClassCastException cce) {
            
            }
        }

        String s1 = o1.toString();
        String s2 = o2.toString();

        return s1.compareTo(s2) * ascending;
    }

    public void sort() {
        Vector dataVectorAux = new Vector();
        dataVectorAux.addAll(dataVector);

        Collections.sort(dataVector, this);

        Integer val = (Integer) ascendCol.get(currCol);
        ascendCol.remove(currCol);
        
        if (val.equals(one)) {
            ascendCol.add(currCol, minusOne);
        } else {
            ascendCol.add(currCol, one);
        }
    }

    public void sortByColumn(int column) {
        this.currCol = column;
        
        sort();
        
        fireTableChanged(new TableModelEvent(this));
    }

    public void addMouseListenerToHeaderInTable(final JTable table) throws Exception {
        final GTableModel sorter = this;
        final JTable tableView = table;
        
        tableView.setColumnSelectionAllowed(false);
        MouseAdapter listMouseListener = new MouseAdapter() {
            
            @Override
            public void mouseClicked(MouseEvent e) {
                try {                    
                    int column = table.getTableHeader().columnAtPoint(new Point(e.getX(), e.getY()));

                    if (column >= 0) {
                        sorter.sortByColumn(column);
                    }
                    
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        
        JTableHeader th = tableView.getTableHeader();
        th.addMouseListener(listMouseListener);
    }
}